package cn.kbkwwk.os.thread;

import cn.kbkwwk.os.global.GlobalData;
import cn.kbkwwk.os.global.Mutex;
import javafx.application.Platform;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * ClassName: MyThreadCase4
 * Package: cn.kbkwwk.os.thread
 * Description:
 *
 * @Date: 2022-06-04 0:40 星期六
 * @Author: Kevin
 */
public class MyThreadCase2 implements Runnable {
    //    线程共享有限的资源，筷子
    public static Integer[] forks = {1, 1, 1, 1, 1};

    public static Boolean isLoop = true;

    public static Lock myLock = new ReentrantLock();//锁对象

    private Mutex mutex;//之多允许4个人就餐

    public MyThreadCase2(Mutex mutex, Integer threadIndex) {
        this.mutex = mutex;
        this.threadIndex = threadIndex;
    }

    private Integer threadIndex;

    public static Boolean getIsLoop() {
        return isLoop;
    }

    public static void setIsLoop(Boolean isLoop) {
        MyThreadCase2.isLoop = isLoop;
    }

    public MyThreadCase2(Integer threadIndex) {
        this.threadIndex = threadIndex;
    }

    public static Integer[] getForks() {
        return forks;
    }

    public static void setForks(Integer[] forks) {
        MyThreadCase2.forks = forks;
    }

    public Integer getThreadIndex() {
        return threadIndex;
    }

    public void setThreadIndex(Integer threadIndex) {
        this.threadIndex = threadIndex;
    }

    @Override
    public void run() {
        System.out.println("执行case1线程" + threadIndex);
        while (isLoop) {
            think();
            mutex.pMutex();
            getFork(threadIndex);
            getFork((threadIndex + 1) % 5);
            eat();
            putFork((threadIndex + 1) % 5);
            putFork(threadIndex);
            mutex.vMutex();
        }
        System.out.println("线程 " + threadIndex + " exit");
    }

    //拿叉子,任意时刻只能有一个人拿叉子
    public synchronized void getFork(Integer index) {
        if (!isLoop) return;
        if (forks[index] > 0) {
            forks[index]--;
            setForkImage(index, GlobalData.blankImage);//将index对应叉子的位置设置为空图片
            if (!isLoop) return;
            String text = "Thread-" + threadIndex + " getting fork" + index + ".." + "\n";
            System.out.print(text);
            addText(text);
        } else {
            Integer isOutput = 0;
            while (forks[index] == 0) {
                if (!isLoop) return;
                if (isOutput == 0) {
                    isOutput = 1;
                    setPeopleImage(threadIndex, GlobalData.waitImage);
                    String text = "Thread-" + threadIndex + " waiting for fork" + index + "!!!" + "\n";
                    System.out.print(text);
                    addText(text);
                }
                mySleep(2000);
            }
            forks[index]--;
            setForkImage(index, GlobalData.blankImage);//将index对应叉子的位置设置为空图片
            if (!isLoop) return;
            String text = "Thread-" + threadIndex + " getting fork" + index + ".." + "\n";
            System.out.print(text);
            addText(text);
        }
    }

    public synchronized void putFork(Integer index) {
        if (!isLoop) return;
        forks[index]++;
        setForkImage(index, GlobalData.forksImage[index]);//将index对应叉子的位置设置为对应形状的叉子图片
        if (!isLoop) return;
        String text = "Thread-" + threadIndex + " putting fork" + index + ".." + "\n";
        System.out.print(text);
        addText(text);
    }


    //给人的位置设置图片
    public void setPeopleImage(Integer peoplePosition, Image image) {
        if (!isLoop) return;
        Platform.runLater(() -> {
            switch (peoplePosition) {
                case 0:
                    GlobalData.myController.getPeopleImage0().setImage(image);
                    break;
                case 1:
                    GlobalData.myController.getPeopleImage1().setImage(image);
                    break;
                case 2:
                    GlobalData.myController.getPeopleImage2().setImage(image);
                    break;
                case 3:
                    GlobalData.myController.getPeopleImage3().setImage(image);
                    break;
                case 4:
                    GlobalData.myController.getPeopleImage4().setImage(image);
                    break;
            }
        });
    }

    //给叉子设置状态
    public void setForkImage(Integer forkPosition, Image image) {
        if (!isLoop) return;
        Platform.runLater(() -> {
            switch (forkPosition) {
                case 0:
                    GlobalData.myController.getForkImage0().setImage(image);
                    break;
                case 1:
                    GlobalData.myController.getForkImage1().setImage(image);
                    break;
                case 2:
                    GlobalData.myController.getForkImage2().setImage(image);
                    break;
                case 3:
                    GlobalData.myController.getForkImage3().setImage(image);
                    break;
                case 4:
                    GlobalData.myController.getForkImage4().setImage(image);
                    break;
            }
        });
    }


    //    吃
    public void eat() {
        if (!isLoop) return;
        setPeopleImage(threadIndex, GlobalData.eatImage);//给当前线程对应下标的人设置成eating图片
        if (!isLoop) return;
        String text = "Thread-" + threadIndex + " eating.." + "\n";
        System.out.print(text);
        addText(text);
    }

    //    思考
    public void think() {
        if (!isLoop) return;
        setPeopleImage(threadIndex, GlobalData.thinkImage);//给当前线程对应下标的人设置成thinking图片
        String text = "Thread-" + threadIndex + " thinking.." + "\n";
        System.out.print(text);
        addText(text);
    }


    //    sleep不会释放锁
    public void mySleep(Integer seconds) {
        if (!isLoop) return;
        try {
            Thread.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public void addText(String str) {
        if (!isLoop) return;
        TextArea textArea = GlobalData.myController.getMyText();
        Platform.runLater(() -> {
            textArea.appendText(str);
        });
        mySleep(500);
    }
}
